package com.escom.healthlc.controller;

import com.escom.healthlc.business.ConsultaBusiness;
import com.escom.healthlc.business.HospitalBusiness;
import com.escom.healthlc.business.PacienteBusiness;
import com.escom.healthlc.business.ReporteBusiness;
import com.escom.healthlc.entidad.ConsultaVO;
import com.escom.healthlc.entidad.EcgORM;
import com.escom.healthlc.entidad.EstudioORM;
import com.escom.healthlc.entidad.HospitalVO;
import com.escom.healthlc.entidad.MedicoVO;
import com.escom.healthlc.entidad.PacienteVO;
import com.escom.healthlc.entidad.PersonaVO;
import com.escom.healthlc.entidad.ReporteGraficaVO;
import com.escom.healthlc.entidad.ReporteVO;
import com.escom.healthlc.utils.Constantes;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import org.primefaces.extensions.event.timeline.TimelineSelectEvent;
import org.primefaces.extensions.model.timeline.TimelineEvent;
import org.primefaces.extensions.model.timeline.TimelineModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ManagedBean(name = "ConsultaController")
@ViewScoped
public class ConsultaController {

    private static final Logger logger = LoggerFactory.getLogger(ConsultaController.class);

    @ManagedProperty("#{ConsultaBusiness}")
    private ConsultaBusiness consultaBusiness;

    @ManagedProperty("#{HospitalBusiness}")
    private HospitalBusiness hospitalBusiness;

    @ManagedProperty("#{PacienteBusiness}")
    private PacienteBusiness pacienteBusiness;

    private PacienteVO pacienteCurrent;
    private MedicoVO medicoCurrent;
    private TimelineModel timeLineModel;
    private List<ConsultaVO> consultasByMedico;
    private List<HospitalVO> catalogoHospitales;
    private ConsultaVO createConsulta;
    private ConsultaVO selectConsulta;
    private HashMap<String, ConsultaVO> mapConsultas;
    private boolean renderPanelAlta;
    private boolean renderPanelConsulta;
    private Date startTimeLine;
    private Date endTimeLine;

    public ConsultaController() {
    }

    @PostConstruct
    public void initConsultaController() {
        mapConsultas = new HashMap();
        pacienteCurrent = null;
        executeLimpiarObjects(null);
        initDateTimeLine();
        getPacienteParam();
        getUsuarioSession();
        getHospitalCat();
    }
    

    public void executeCrearCita(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        if (createConsulta.getFechaFinalDate().after(createConsulta.getFechaInicioDate())) {
            createConsulta.setIdPaciente(pacienteCurrent.getIdPaciente());
            createConsulta.setIdMedico(medicoCurrent.getIdMedico());
            consultaBusiness.crearConsulta(createConsulta);
            int estado = consultaBusiness.getEstado();
            String messageEstado = consultaBusiness.getMessageEstado();
            switch (estado) {
                case Constantes.SIN_ERROR:
                    facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO, Constantes.MESSAGE_TITLE, messageEstado);
                    facesContext.addMessage(null, facesMessage);
                    break;
                case Constantes.ERROR_BASE_DATOS:
                    facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Constantes.MESSAGE_TITLE, messageEstado);
                    facesContext.addMessage(null, facesMessage);
                    break;
            }
        } else {
            facesMessage = new FacesMessage(FacesMessage.SEVERITY_WARN, Constantes.MESSAGE_TITLE, "La fecha final debe ser posterior a la fecha inicial.");
            facesContext.addMessage(null, facesMessage);
        }
        executeLimpiarObjects(acEvt);
    }

    public void executeConsultaCitas(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        String contextPath = facesContext.getExternalContext().getRequestContextPath();
        timeLineModel = new TimelineModel();
        consultasByMedico = consultaBusiness.obtenerConsulta(medicoCurrent, pacienteCurrent);
        int estado = consultaBusiness.getEstado();
        String messageEstado = consultaBusiness.getMessageEstado();
        switch (estado) {
            case Constantes.SIN_ERROR:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO, Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                for (int i = 0; i < consultasByMedico.size(); i++) {
                    ConsultaVO consulta = consultasByMedico.get(i);
                    String key = "Consulta " + (i + 1);
                    mapConsultas.put(key, consulta);
                    timeLineModel.add(new TimelineEvent(key, consulta.getFechaInicioDate(), consulta.getFechaFinalDate()));
                }
                break;
            case Constantes.ERROR_BASE_DATOS:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
        }
        executeChangeToRetrieve();
    }

    public void executeActulizarCita(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        consultaBusiness.actualizarConsulta(selectConsulta);
        int estado = consultaBusiness.getEstado();
        String messageEstado = consultaBusiness.getMessageEstado();
        switch (estado) {
            case Constantes.SIN_ERROR:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO, Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
            case Constantes.ERROR_BASE_DATOS:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
        }
        executeLimpiarObjects(acEvt);

    }

    public void executeEliminarCita(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        consultaBusiness.eliminarConsulta(selectConsulta);
        int estado = consultaBusiness.getEstado();
        String messageEstado = consultaBusiness.getMessageEstado();
        switch (estado) {
            case Constantes.SIN_ERROR:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_INFO, Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
            case Constantes.ERROR_BASE_DATOS:
                facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Constantes.MESSAGE_TITLE, messageEstado);
                facesContext.addMessage(null, facesMessage);
                break;
        }
        executeLimpiarObjects(acEvt);

    }

    public void selectTimeLine(TimelineSelectEvent selectEvt) {
        TimelineEvent timeline = selectEvt.getTimelineEvent();
        String key = (String) timeline.getData();
        selectConsulta = mapConsultas.get(key);
        logger.debug("selectConsulta {}", selectConsulta.toString());
    }

    public void executeLimpiarObjects(ActionEvent acEvt) {
        timeLineModel = new TimelineModel();
        createConsulta = new ConsultaVO();
        createConsulta.setHospital(new HospitalVO());
        selectConsulta = new ConsultaVO();
        selectConsulta.setHospital(new HospitalVO());
        renderPanelAlta = false;
        renderPanelConsulta = false;
    }

    public void initDateTimeLine() {
        int anio = Calendar.getInstance().get(Calendar.YEAR);
        int mes = Calendar.getInstance().get(Calendar.MONTH);
        int diaMes = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
        Calendar dateStart = Calendar.getInstance();
        Calendar dateEnd = Calendar.getInstance();
        dateStart.set(anio, mes, diaMes, 0, 0);
        dateEnd.set(anio, mes, diaMes + 1, 0, 0);
        startTimeLine = dateStart.getTime();
        endTimeLine = dateEnd.getTime();
    }

    public void executeChangeToCreate() {
        if (pacienteCurrent == null) {
            try {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                ExternalContext externalContext = facesContext.getExternalContext();
                String path = ((ServletContext) externalContext.getContext()).getContextPath();
                externalContext.redirect(path + "/view/med-paciente.jsf?select=0");
            } catch (IOException ex) {
                logger.error("Logger Error: {}", ex.getCause().getMessage());
                logger.error("Logger Error: {}", ex.fillInStackTrace().toString());
            }
        }
        renderPanelAlta = true;
        renderPanelConsulta = false;
    }

    public void executeChangeToRetrieve() {
        renderPanelAlta = false;
        renderPanelConsulta = true;
    }

    public void getUsuarioSession() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
        HttpSession httpSession = request.getSession(true);
        medicoCurrent = (MedicoVO) httpSession.getAttribute("usuarioActivio");
    }

    private void getPacienteParam() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        pacienteCurrent = (PacienteVO) externalContext.getSessionMap().get("idPacienteParam");
    }

    private void getHospitalCat() {
        catalogoHospitales = hospitalBusiness.obtenerHospital();
    }

    public void setConsultaBusiness(ConsultaBusiness consultaBusiness) {
        this.consultaBusiness = consultaBusiness;
    }

    public void setHospitalBusiness(HospitalBusiness hospitalBusiness) {
        this.hospitalBusiness = hospitalBusiness;
    }

    public void setPacienteBusiness(PacienteBusiness pacienteBusiness) {
        this.pacienteBusiness = pacienteBusiness;
    }

    public TimelineModel getTimeLineModel() {
        return timeLineModel;
    }

    public void setTimeLineModel(TimelineModel timeLineModel) {
        this.timeLineModel = timeLineModel;
    }

    public List<ConsultaVO> getConsultasByMedico() {
        return consultasByMedico;
    }

    public void setConsultasByMedico(List<ConsultaVO> consultasByMedico) {
        this.consultasByMedico = consultasByMedico;
    }

    public ConsultaVO getCreateConsulta() {
        return createConsulta;
    }

    public void setCreateConsulta(ConsultaVO createConsulta) {
        this.createConsulta = createConsulta;
    }

    public List<HospitalVO> getCatalogoHospitales() {
        return catalogoHospitales;
    }

    public void setCatalogoHospitales(List<HospitalVO> catalogoHospitales) {
        this.catalogoHospitales = catalogoHospitales;
    }

    public boolean isRenderPanelAlta() {
        return renderPanelAlta;
    }

    public void setRenderPanelAlta(boolean renderPanelAlta) {
        this.renderPanelAlta = renderPanelAlta;
    }

    public boolean isRenderPanelConsulta() {
        return renderPanelConsulta;
    }

    public void setRenderPanelConsulta(boolean renderPanelConsulta) {
        this.renderPanelConsulta = renderPanelConsulta;
    }

    public ConsultaVO getSelectConsulta() {
        return selectConsulta;
    }

    public void setSelectConsulta(ConsultaVO selectConsulta) {
        this.selectConsulta = selectConsulta;
    }

    public Date getStartTimeLine() {
        return startTimeLine;
    }

    public void setStartTimeLine(Date startTimeLine) {
        this.startTimeLine = startTimeLine;
    }

    public Date getEndTimeLine() {
        return endTimeLine;
    }

    public void setEndTimeLine(Date endTimeLine) {
        this.endTimeLine = endTimeLine;
    }

    public PacienteVO getPacienteCurrent() {
        return pacienteCurrent;
    }

    public void setPacienteCurrent(PacienteVO pacienteCurrent) {
        this.pacienteCurrent = pacienteCurrent;
    }

    @ManagedProperty("#{ReporteBusiness}")
    private ReporteBusiness reporteBusiness;

    private String tipoArrimiaString;
    private List<ReporteGraficaVO> reporteGraficaSano;
    private List<ReporteGraficaVO> reporteGraficaTaquicardia;
    private List<ReporteGraficaVO> reporteGraficaBradicardia;
    private List<ReporteGraficaVO> reporteGraficaFibrilacion;

  

    public void executeCrearReporte(ActionEvent acEvt) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        FacesMessage facesMessage;
        ReporteVO consultarPaciente = reporteBusiness.consultarPaciente(pacienteCurrent);
        if (consultarPaciente != null) {
            consultarPaciente.setNombrePaciente(consultarPaciente.getNombrePaciente() + " " + consultarPaciente.getApPaternoPaciente() + " " + consultarPaciente.getApMaternoPaciente());
            consultarPaciente.setNombreMedico(consultarPaciente.getNombreMedico() + " " + consultarPaciente.getApPaternoMedico() + " " + consultarPaciente.getApMaternoMedico());
            String archivoPrueba = consultarPaciente.getArchivoPrueba();
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File(Constantes.PATH_WEB_VIRTUAL + "\\" + archivoPrueba + ".txt")));
                EstudioORM readObject = (EstudioORM) objectInputStream.readObject();
                String[] mediaOximetro = reporteBusiness.obtenerMediaOximetro(readObject.getOximetros());
                String temperatura = reporteBusiness.obtenerMediaTemperatura(readObject.getTemperaturas());
                List<EcgORM> arritmias = readObject.getArritmias();
                obtenerSegmento(arritmias);
                consultarPaciente.setTemperatura(temperatura);
                consultarPaciente.setOxigeno(mediaOximetro[0]);
                consultarPaciente.setPulsaciones(mediaOximetro[1]);
//                consultarPaciente.setSegmentoArritmia(segmentoArritmia);
                consultarPaciente.setTipoArritmia(tipoArrimiaString);
                consultarPaciente.setSanoElectrocadiograma(reporteGraficaSano);
                consultarPaciente.setTaquicardiaElectrocadiograma(reporteGraficaTaquicardia);
                consultarPaciente.setBradicardiaElectrocadiograma(reporteGraficaBradicardia);
                consultarPaciente.setFibrilacionElectrocadiograma(reporteGraficaFibrilacion);
//                consultarPaciente.setxLine(xLine);
//                consultarPaciente.setTitleSerie("Electrocadiograma");
                exportarPDF(consultarPaciente);
            } catch (FileNotFoundException ex) {
                java.util.logging.Logger.getLogger(ConsultaController.class.getName()).log(Level.SEVERE, null, ex);
                logger.error("Error Logger : {}", ex.getCause().getMessage());
                logger.error("Error Logger : {}", ex.fillInStackTrace().toString());
            } catch (IOException ex) {
                java.util.logging.Logger.getLogger(ConsultaController.class.getName()).log(Level.SEVERE, null, ex);
                logger.error("Error Logger : {}", ex.getCause().getMessage());
                logger.error("Error Logger : {}", ex.fillInStackTrace().toString());
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(ConsultaController.class.getName()).log(Level.SEVERE, null, ex);
                logger.error("Error Logger : {}", ex.getCause().getMessage());
                logger.error("Error Logger : {}", ex.fillInStackTrace().toString());
            }
        } else {
            facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, Constantes.MESSAGE_TITLE, "No existe una consulta asociada al nombre.");
            facesContext.addMessage(null, facesMessage);
        }
    }

    public void exportarPDF(ReporteVO consultarPaciente) {
        try {
            Collection<ReporteVO> entidad = new ArrayList<ReporteVO>();
            entidad.add(consultarPaciente);
            String fileName = consultarPaciente.getNombrePaciente();
            JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(entidad);
            String reportPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/resources/reports/ReportePaciente.jasper");
            JasperPrint jasperPrint;
            jasperPrint = JasperFillManager.fillReport(reportPath, new HashMap(), beanCollectionDataSource);
            HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
            httpServletResponse.addHeader("Content-disposition", "attachment; filename=" + fileName + " Reporte Medico.pdf");
            ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();

            JRExporter exporter = new JRPdfExporter();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, servletOutputStream); // your output goes here

            exporter.exportReport();
            FacesContext.getCurrentInstance().responseComplete();
        } catch (JRException ex) {
            logger.error("Logger Error: {}", ex.getCause().getMessage());
            logger.error("Logger Error: {}", ex.fillInStackTrace().toString());
        } catch (IOException ex) {
            logger.error("Logger Error: {}", ex.getCause().getMessage());
            logger.error("Logger Error: {}", ex.fillInStackTrace().toString());
        }
    }

    public void obtenerSegmento(List<EcgORM> arritmias) {
        tipoArrimiaString = "";
        reporteGraficaSano = new ArrayList<>();
        reporteGraficaTaquicardia = new ArrayList<>();
        reporteGraficaBradicardia = new ArrayList<>();
        reporteGraficaFibrilacion = new ArrayList<>();
        String taquicardia = "", bradicardia = "", fibrilacionAuricular = "";
        for (int i = 0; i < arritmias.size(); i++) {
            ReporteGraficaVO tickGrafica = new ReporteGraficaVO();
            EcgORM arritmia = arritmias.get(i);
            double value = Double.parseDouble(arritmia.getValue());
            int tipoArritmia = Integer.parseInt(arritmia.getTipoArritmia());
            switch (tipoArritmia) {
                case 0:
                    taquicardia = "Taquicardia";
                    tickGrafica.setGrafica(taquicardia);
                    tickGrafica.setxValue(i);
                    tickGrafica.setyValue(value);
                    if (reporteGraficaSano.size() < 100) {
                        reporteGraficaSano.add(tickGrafica);
                    }
                    break;
                case 1:
                    taquicardia = "Taquicardia";
                    tickGrafica.setGrafica(taquicardia);
                    tickGrafica.setxValue(i);
                    tickGrafica.setyValue(value);
                    if (reporteGraficaTaquicardia.size() < 100) {
                        reporteGraficaTaquicardia.add(tickGrafica);
                    }
                    break;
                case 2:
                    bradicardia = "Bradicardia";
                    tickGrafica.setGrafica(bradicardia);
                    tickGrafica.setxValue(i);
                    tickGrafica.setyValue(value);
                    if (reporteGraficaBradicardia.size() < 100) {
                        reporteGraficaBradicardia.add(tickGrafica);
                    }
                    break;
                case 3:
                    fibrilacionAuricular = "Fibrilacion Auricular";
                    tickGrafica.setGrafica(fibrilacionAuricular);
                    tickGrafica.setxValue(i);
                    tickGrafica.setyValue(value);
                    if (reporteGraficaFibrilacion.size() < 100) {
                        reporteGraficaFibrilacion.add(tickGrafica);
                    }
                    break;
            }
        }
        tipoArrimiaString = taquicardia + " " + bradicardia + " " + fibrilacionAuricular;
        logger.debug("TipoArritmia {}", tipoArrimiaString);
    }

    public void setReporteBusiness(ReporteBusiness reporteBusiness) {
        this.reporteBusiness = reporteBusiness;
    }


}
